#include "LicenseChecking.h"
#include <wx/txtstrm.h>
#include "CurrentAppHeaders.h"
#include <wx/xml/xml.h>


//for general use
LicenseChecking::LicenseChecking(int key, License *license2Check, LinkListLicense *validLicenses, TNodBase *parent/*, bool countInMainApp*/, EsetInfo *esetInfo, unsigned int actions, wxThreadKind kind)
        : wxThread(kind)
{
    m_key = key;
    m_license = license2Check;
    m_validLicenses = validLicenses;
    m_parent = parent;
    //m_countInMainApp = countInMainApp;
    m_esetInfo = esetInfo;
    m_actions = actions;
    m_checkedLicenses = NULL;
    m_DownloadEvent = NULL;
    m_HandlerForEvent = NULL;
    m_LicWithNoExpirationOnly = false;
}

//used to check a single license
LicenseChecking::LicenseChecking(License *license2Check, TNodBase *parent, wxThreadKind kind)
    : wxThread(kind)
{
    m_key = -1;
    m_license = license2Check;
    m_validLicenses = NULL;
    m_parent = parent;
    //m_countInMainApp = false;
    m_esetInfo = NULL;
    m_actions = CHECK_VALIDITY;
    m_checkedLicenses = NULL;
    m_DownloadEvent = NULL;
    m_HandlerForEvent = NULL;
    m_LicWithNoExpirationOnly = false;
}

void *LicenseChecking::Entry()
{
    if ( m_license == NULL ) //the thread works with the license only
    {
        Checked();
        return NULL;
    }
    else
        m_license->SetValid(false);

    wxListKey strKey(m_license->GetUsername() + wxT("@") + m_license->GetPassword());
    
    if ( m_checkedLicenses != NULL && m_checkedLicenses->Find(strKey) != NULL )
    {
        Checked();
        return NULL;
    }

    if ( (m_actions & CHECK_VALIDITY) == CHECK_VALIDITY )
        CheckValidity();

    bool checkExpirationOnly = (m_actions == CHECK_EXPIRATIONDATE);
    bool checkBoth = (m_actions == (CHECK_EXPIRATIONDATE|CHECK_VALIDITY));
    if ( checkExpirationOnly == true || ( checkBoth && m_license->IsValid() ) )
        CheckExpirationDate();

    Checked();
    return NULL;
}
void LicenseChecking::Exit()
{
}

void LicenseChecking::SendExtraEvent(int ID, License * license)
{
    if ( m_DownloadEvent != NULL && m_HandlerForEvent != NULL )
    {
        wxCommandEvent *newEvent = new wxCommandEvent(*m_DownloadEvent);
        newEvent->SetClientData(license);
        newEvent->SetInt(ID);
    
        wxPostEvent(m_HandlerForEvent, *newEvent );
    }
}
void LicenseChecking::Checked()
{
    
    /*
    if ( m_countInMainApp == true )
    {
        //wxCriticalSectionLocker locker(wxGetApp().m_MutexLicensesCounter); //lock, the thread needs to change the m_checkedLicenses value
        wxGetApp().m_checkedLicenses++;

    }
    */
    if ( m_parent != NULL )
        m_parent->RemoveChildThread((wxThread *)this);//removes the reference to this thread in the parent thread     
}
/*
wxString LicenseChecking::GetValueTagFromXml(const wxString xml)
{//returns the value of the property VALUE in a xml tag
 //example, for: <NODE NAME="ExpirationDate" VALUE="4b4126b0" TYPE="DWORD" />
 //         the function returns: 4b4126b0
    int posBegin = xml.Find(wxT("VALUE=\""));
    int posEnd = 0;
    if ( posBegin >= 0 )
    {
        posBegin += 7;// 7 = length of: VALUE="
        posEnd = xml.find(wxT("\" "),posBegin);

        if ( posEnd > posBegin )
            return xml.Mid(posBegin,posEnd - posBegin);
    }
    return wxT("");
}
*/
//returns the xml used to request the expire date of a license
wxString LicenseChecking::GetValidityXML()
{
    wxPlatformInfo osInfo;
    wxString languageId;
    wxString OsVersion;

    languageId.Printf(wxT("%ld"),( m_esetInfo != NULL ? m_esetInfo->GetLanguageId() : 0x409));

    OsVersion.Printf(wxT("%d.%d"),osInfo.GetOSMajorVersion(),osInfo.GetOSMinorVersion());

    wxString userPassEncoded = License::Encode2Validate(m_license->GetUsername(),m_license->GetPassword());
    wxString product = ( m_esetInfo != NULL ? m_esetInfo->GetVersionType() : wxT("eav") );
    wxString version = ( m_esetInfo != NULL ? m_esetInfo->GetStrVersion() : wxT("4.0.474.0") );
    
    wxString xml = wxT("<?xml version=\"1.0\" encoding=\"utf-8\"?>") wxT("\n")
        wxT("<GETLICEXP>") wxT("\n")
            wxT("<SECTION ID=\"1000103\">") wxT("\n")
                wxT("<LICENSEREQUEST>") wxT("\n")
                wxT("<NODE NAME=\"UsernamePassword\" VALUE=\"") + userPassEncoded + wxT("\" TYPE=\"STRING\" />") wxT("\n")
                    wxT("<NODE NAME=\"Product\" VALUE=\"") + product + wxT("\" TYPE=\"STRING\" />") wxT("\n")
                    wxT("<NODE NAME=\"Version\" VALUE=\"") + version + wxT("\" TYPE=\"STRING\" />") wxT("\n")
                    wxT("<NODE NAME=\"Language\" VALUE=\"") + languageId + wxT("\" TYPE=\"DWORD\" />") wxT("\n")
                    wxT("<NODE NAME=\"UpdateTag\" VALUE=\"\" TYPE=\"STRING\" />") wxT("\n")
                    wxT("<NODE NAME=\"System\" VALUE=\"") + OsVersion + wxT("\" TYPE=\"STRING\" />") wxT("\n")
                wxT("</LICENSEREQUEST>") wxT("\n")
            wxT("</SECTION>") wxT("\n")
        wxT("</GETLICEXP>") wxT("\n");

    xml.Append((wxChar)0);
    return xml;
}

void LicenseChecking::CheckValidity()
{
    wxInputStream *httpStream = NULL;
    int responseCode = 0;

    wxString esetServer = SETTINGS->GetEsetServer();
    wxString esetFile = SETTINGS->GetEsetFile();
    
    wxString path = Utils::AddProtocol(esetServer + esetFile);
    wxHTTPBuilder *get = Utils::SockInit( SETTINGS->GetProxySettings() );    

    if ( path.IsEmpty() )
        return;

    get->Authenticate(m_license->GetUsername(), m_license->GetPassword());

    httpStream = get->GetInputStream(path);
    responseCode = get->GetResponse();
    get->Close();
    wxDELETE(httpStream);
#ifdef LOCALSERVER
    if ( true )
#else
    if ( responseCode > 0 )
#endif
    {            
        wxListKey strKey(m_license->GetUsername() + wxT("@") + m_license->GetPassword());

        License *newLicense = NULL;

        //wxMessageBox(strKey.GetString());
        
        if ( m_checkedLicenses != NULL )
        {
            newLicense = new License(m_license);
            m_checkedLicenses->Append(strKey.GetString(),newLicense);
        }

        //wxString msg;
        //msg.Printf(wxT("%d"),responseCode);
        //wxMessageBox(msg);

#ifdef LOCALSERVER
        if ( true )
#else
        if ( responseCode == 200 )
#endif
        {
            m_license->SetValid(true);

            if ( m_validLicenses != NULL && m_LicWithNoExpirationOnly == false )
            {                    
                //*wxCriticalSectionLocker locker(wxGetApp().m_MutexValidLicensesList);
                //if the license is not in the list
                if ( m_validLicenses->GetCount() < wxGetApp().m_validLicenses2Get ) 
                {
                    wxCriticalSectionLocker locker(wxGetApp().m_MutexValidLicensesList);
                    if (m_validLicenses->Find(strKey) == NULL )
                    {
                        if ( newLicense == NULL )
                            newLicense = new License(m_license);
                        else
                            newLicense->SetValid(true);

                        m_validLicenses->Append(strKey.GetString(),newLicense);
                        //wxLogError(wxT("Username: ") + m_license->GetUsername());

                        SendExtraEvent(1,newLicense);
                    }
                }
                    
            }
        }
        else
            m_license->SetValid(false);
    }
}
//#include <wx/sstream.h>
//#include <wx/filename.h>
void LicenseChecking::CheckExpirationDate()
{   
    bool isServerOk = false;        
    wxString lineOfData;  //one line of information from socket
    wxInputStream *httpStream = NULL;    
    wxHTTPBuilder *get = Utils::SockInit( SETTINGS->GetProxySettings() );

    wxString path = SETTINGS->GetExpirationServer();
    //path=wxT("http://exp02.eset.com/getlicexp");

#ifdef LOCALSERVER
    path = wxT("http://localhost/getlicexp");
#endif
    
    get->SetValue(wxT("checklic="),GetValidityXML(),wxHTTPBuilder::wxHTTP_TYPE_POST);  
    get->SetHeader(wxT("Content-Type"), wxT("application/x-www-form-urlencoded"));

    httpStream = get->GetInputStream(path);                                   //gets the stream manager  
    
    //wxString msg;
    //msg.Printf(wxT("response: %d"),get->GetResponse());
    //wxMessageBox(msg);

    if ( get->GetResponse() >= 200 && get->GetResponse() < 300 
        && httpStream != NULL && get->GetError() == wxPROTO_NOERR 
        && get->GetHeader(wxT("Content-Type")).Contains(wxT("xml")) 
        ) 
        isServerOk = true;

    if ( isServerOk == true )
    {
        //wxString msg;
        //msg.Printf(wxT("%s - %s"), m_license->GetUsername(), m_license->GetPassword());
        //wxMessageBox(msg);


        int c = 0;
        wxTextInputStream in(*httpStream);
        
        int lines2Skip = SETTINGS->GetLines2SkipXml();
        for (c = 0; c < lines2Skip ; c++)
        {
            in.ReadLine();
        }

        /*wxString string;
        while (1)
        {
            wxString readedLine = in.ReadLine();
            if (readedLine.Len() > 0)
                string += in.ReadLine();
            else 
                break;
            
        }*/

        wxXmlDocument doc(*httpStream);
 
        if ( !doc.GetRoot() || doc.GetRoot()->GetName().CmpNoCase(wxT("GETLICEXP")) != 0 )
            return;
        if ( !doc.IsOk() )
            return;

        
        wxXmlNode *child = doc.GetRoot()->GetChildren();
        
        bool continueReading = true;

        while ( child && continueReading ) 
        {
            if (child->GetName().CmpNoCase(wxT("SECTION")) == 0 && child->GetPropVal(wxT("ID"), wxT("")) == wxT("1000103") ) 
            {
                wxXmlNode *subChild = child->GetChildren();
                while (subChild && continueReading )
                {
                    if (subChild->GetName().CmpNoCase(wxT("LICENSEINFO")) == 0)
                    {
                        wxXmlNode *dataChild = subChild->GetChildren();
                        while (dataChild && continueReading )
                        {
                            if (dataChild->GetName().CmpNoCase(wxT("NODE")) == 0)
                            {
                                if ( dataChild->GetPropVal(wxT("NAME"),wxT("")).CmpNoCase(wxT("ExpirationDate")) == 0 )
                                {
                                    wxString valueDate = dataChild->GetPropVal(wxT("VALUE"),wxT(""));
                                    unsigned long dateInms = Utils::Hex2Dec(valueDate);
                                    m_license->SetExpirationDate(dateInms);
                                                                        
                                }
                                else if ( dataChild->GetPropVal(wxT("NAME"),wxT("")).CmpNoCase(wxT("ExpirationState")) == 0 )
                                {
                                    wxString valueState = dataChild->GetPropVal(wxT("VALUE"),wxT(""));
                                    unsigned long state = Utils::Hex2Dec(valueState);
                                    m_license->SetExpirationState(state);

                                    License* newLicense = new License(m_license);
                                    if ( m_checkedLicenses != NULL )
                                    {
                                        AppendLicense2List(newLicense, m_checkedLicenses);
                                    }
                                    if ( state == 0 && m_LicWithNoExpirationOnly == true && m_validLicenses )
                                    {
                                        AppendLicense2List(newLicense, m_validLicenses);
                                    }
                                    
                                    SendExtraEvent(3,newLicense);

                                    continueReading = false;
                                }                                
                            }
                            dataChild = dataChild->GetNext();
                        }
                    }
                    subChild = subChild->GetNext();
                }
            }
            child = child->GetNext();
        }

        /*
        wxTextInputStream in(*httpStream);
        while (!httpStream->Eof() && !TestDestroy())
        {
            lineOfData = in.ReadLine();
            lineOfData.Trim(true);
            lineOfData.Trim(false);
            
            if ( lineOfData.Matches(wxT("*<NODE NAME=\"ExpirationDate\" VALUE=\"*\" TYPE=\"DWORD\"*")) )
            {//checks for the node: <NODE NAME="ExpirationDate" VALUE="XXXXX" TYPE="DWORD" />
             // XXXXX is a hexadecimal number wich represents the expiration date in milliseconds
                wxString valueDate = GetValueTagFromXml(lineOfData);
                unsigned long dateInms;
                dateInms = Utils::Hex2Dec(valueDate);
                m_license->SetExpirationDate(dateInms);
                
                //wxMessageBox(valueDate);
                SendExtraEvent(3,m_license);
            }                
            else if ( lineOfData.Matches(wxT("*<NODE NAME=\"ExpirationState\" VALUE=\"*\" TYPE=\"DWORD\"*")) )
            {//checks for the node: <NODE NAME="ExpirationState" VALUE="X" TYPE="DWORD" />
             //the X is a number which can be:
             // 0: License is Ok      1: License is near of expire     2: License is expired                    
                wxString valueState = GetValueTagFromXml(lineOfData);
                unsigned long state = Utils::Hex2Dec(valueState);
                m_license->SetExpirationState(state);

                License* newLicense = NULL;
                if ( m_checkedLicenses != NULL )
                {
                    newLicense = new License(m_license);
                    AppendLicense2List(newLicense, m_checkedLicenses);
        
                }
                if ( state == 0 )
                {
                    if ( m_LicWithNoExpirationOnly == true && m_validLicenses != NULL )
                    {
                        if ( !newLicense )
                            newLicense = new License(m_license);
                        AppendLicense2List(newLicense, m_validLicenses);
                    }
                }

                break;
            }
        }
        */
    }
    if ( get != NULL )
    {
        get->Stop();
        get->Close();
    }
    wxDELETE(httpStream);
}
void LicenseChecking::AppendLicense2List(License* license2Append, LinkListLicense *licensesList)
{
    if ( license2Append && licensesList )
    {
        wxListKey strKey(license2Append->GetUsername() + wxT("@") + license2Append->GetPassword());
        licensesList->Append(strKey.GetString(),license2Append);
    }
}